package com.zb.controller;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ConcurrentAccessException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.qq.connect.QQConnectException;
import com.qq.connect.api.OpenID;
import com.qq.connect.api.qzone.UserInfo;
import com.qq.connect.javabeans.AccessToken;
import com.qq.connect.javabeans.qzone.UserInfoBean;
import com.qq.connect.oauth.Oauth;
import com.zb.bean.Article;
import com.zb.bean.User;
import com.zb.bean.UserRoleRef;
import com.zb.enums.Enums;
import com.zb.qo.ArticleQo;
import com.zb.qo.LoginQo;
import com.zb.qo.RegisterQo;
import com.zb.service.ArticleService;
import com.zb.service.UserRoleService;
import com.zb.service.UserService;
import com.zb.util.CryptoUtils;
import com.zb.util.LoggerUtil;
import com.zb.vo.AjaxResult;
import com.zb.vo.PageVo;

/**
 * 会员登录与验证
 * 
 * 作者: zhoubang 日期：2015年4月1日 下午5:30:25
 */
@Controller
public class LoginRegisterController extends BaseController {

    @Resource(name="userServiceImpl")
    private UserService userService;
    
    @Autowired
    private ArticleService articleService;
    
    @Resource(name="userRoleServiceImpl")
    private UserRoleService userRoleService;
    
    /**
     * 登录
     * 
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ModelAndView loginFailed(HttpServletRequest req, HttpServletResponse res,
            @Valid LoginQo loginQo,BindingResult bindingResult) {
        String loginType = req.getParameter("loginType");
        
        ModelAndView mav = modelAndView("/login");
        // 参数错误验证
        if (bindingResult.hasErrors()) {
            mav.addObject("loginErrorMsg", "登录参数错误，请检查必填项是否输入正确");
            if(loginType != null && loginType.equals("mobile")){//手机端登录
                mav.setViewName("/mobile/login");
            }
            return mav;
        }
        
        // 错误消息
        String loginErrorMsg = "";
        UsernamePasswordToken token = new UsernamePasswordToken(loginQo.getUserName(), CryptoUtils.encodeMD5(loginQo.getPassword()));
        Subject subject = null;
        try {
            // 设置是否记住我
            if (null == loginQo.getRememberMe() || "".equals(loginQo.getRememberMe().trim()) || "off".equals(loginQo.getRememberMe())) {
                token.setRememberMe(false);
            } else {
                token.setRememberMe(true);
            }
            SecurityUtils.getSubject().login(token);
            subject = SecurityUtils.getSubject();
            LoggerUtil.LoggerFormatPattern("用户：{0} 登录成功", subject.getPrincipal());
            
            SecurityUtils.getSubject().getSession().setTimeout(1000 * 60 * 60);
            req.getSession().setAttribute("nickName", subject.getPrincipal());;
            
        } catch (Throwable e) {
            //UnknownAccountException   该账号不存在
            //CredentialsException      密码错误
            if (e instanceof LockedAccountException) {
                loginErrorMsg = "该账号已被锁定，请联系管理员解锁";
            } else if (e instanceof ConcurrentAccessException) {
                loginErrorMsg = "该账户已经登录";
            } else if (e instanceof AuthenticationException) {
                loginErrorMsg = "账号不存在或密码错误";
            } else {
                LoggerUtil.LoggerWarn("未知的登陆错误", e);
                loginErrorMsg = "未知的登陆错误";
            }
        }
        
        // 登录出现错误
        if (!"".equals(loginErrorMsg) && loginErrorMsg.length() > 0) {
            if(loginType != null && loginType.equals("mobile")){//手机端登录
                return this.modelAndView("/mobile/login","loginErrorMsg", loginErrorMsg);
            }
            return this.modelAndView("/login","loginErrorMsg", loginErrorMsg);
        }

        /**
         * 利用ModelAndView也能实现forward、redirect： forward转发: return
         * ModelAndView("forward:/index/mailList.shtml"); redirect重定向: return
         * ModelAndView("redirect:/index/mailList.shtml");
         */
        if(subject.getPrincipal().equals("zhoubang")){
            return this.redirectModelAndView("/system");
        }else{
            if(loginType != null && loginType.equals("mobile")){//手机端登录，跳转到手机端首页
                return this.redirectModelAndView("/mobile/index");
            }
            return this.redirectModelAndView("/center");
        }
    }

    /**
     * 注销
     * 
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/logout2", method = RequestMethod.GET)
    public ModelAndView logout(HttpServletRequest req, HttpServletResponse res,String device)
            throws Exception {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            LoggerUtil.LoggerFormatPattern("用户 {0} 退出登录", subject.getPrincipal());

            subject.logout();
        }
        if(device != null && device.equals("mobile")){
            return redirectModelAndView("/mobile/toLogin");
        }
        return redirectModelAndView("/toLogin");
    }
    
    /**
     * 会员注册
     * 
     * 作者: zhoubang 
     * 日期：2015年4月22日 下午5:26:53
     * @param req
     * @param res
     * @param registerQo
     * @param bindingResult
     * @return
     */
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResult<Object> register(HttpServletRequest req, HttpServletResponse res,
            @Valid RegisterQo registerQo,BindingResult bindingResult){
        //若校验出没有填写完整的必填参数，则直接提示用户
        AjaxResult<Object> result = new AjaxResult<Object>();
        if (bindingResult.hasErrors()) {
            result.setCode(204);
            result.setMsg("注册资料填写不全");
            return result;
        }
        //校验2次密码是否正确
        if(!registerQo.getPassword().equals(registerQo.getPasswordOk())){
            result.setCode(202);
            result.setMsg("两次密码输入不一致");
            return result;
        }
        try {
            //检查账户名称是否重复
            User userInfo = userService.getUserByName(registerQo.getUserName());
            if(userInfo != null){
                result.setCode(201);
                result.setMsg("该账户名已经存在，请重新输入");
                return result;
            }
            //注册
            userService.register(registerQo.buildUserInfo());
            
            //注册成功后，默认为用户设置user角色
            User user = userService.getUserByName(registerQo.getUserName());
            UserRoleRef ur = new UserRoleRef();
            ur.setUserId(user.getId());
            ur.setRoleId(Enums.Role.USER.getId());
            userRoleService.addUserRole(ur);
            
        } catch (Exception e) {
            result.setMsg("注册失败");
            e.printStackTrace();
        }
        return result;
    }
    
    /**
     * QQ登陆
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("qqLogin")
    public void qqLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html;charset=utf-8");
        try {
            response.sendRedirect(new Oauth().getAuthorizeURL(request));
        } catch (QQConnectException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * QQ登陆回调
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("afterQQLogin2")
    public ModelAndView afterQQLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mav = null;
        String loginUserName = null;
        String loginUserPwd = null;
        try {
            AccessToken accessTokenObj = (new Oauth()).getAccessTokenByRequest(request);

            String accessToken = null, openID = null, nickName = null;

            if (accessTokenObj.getAccessToken().equals("")) {
                //我们的网站被CSRF攻击了或者用户取消了授权
                //做一些数据统计工作
                //System.out.print("没有获取到响应参数");
                mav = new ModelAndView("login");
                mav.addObject("loginErrorMsg", "QQ快捷登陆失败");
            } else {
                accessToken = accessTokenObj.getAccessToken();

                // 利用获取到的accessToken 去获取当前用的openid -------- start
                OpenID openIDObj =  new OpenID(accessToken);
                openID = openIDObj.getUserOpenID();
                
                UserInfo qzoneUserInfo = new UserInfo(accessToken, openID);
                UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
                if (userInfoBean.getRet() == 0) {
                    nickName = userInfoBean.getNickname();
                    //out.println(userInfoBean.getGender() + "<br/>");
                    //out.println("黄钻等级： " + userInfoBean.getLevel() + "<br/>");
                    //out.println("会员 : " + userInfoBean.isVip() + "<br/>");
                    //out.println("黄钻会员： " + userInfoBean.isYellowYearVip() + "<br/>");
                    //out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL30() + "/><br/>");
                    //out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL50() + "/><br/>");
                    //out.println("<image src=" + userInfoBean.getAvatar().getAvatarURL100() + "/><br/>");
                } else {
                    mav = new ModelAndView("login");
                    mav.addObject("loginErrorMsg", "QQ快捷登陆失败");
                }
                
                //检查该QQ是否已经注册登录过
                User userObj = userService.getUserByOpenId(openID);
                if(userObj == null){
                    //注册
                    RegisterQo qo = new RegisterQo();
                    qo.setOpenId(openID);
                    qo.setPassword("123456");
                    //qo.setPasswordOk(CryptoUtils.encodeMD5("123456"));
                    qo.setUserName(nickName);
                    userService.register(qo.buildUserInfo());
                    
                    //注册成功后，默认为用户设置user角色
                    User user = userService.getUserByName(qo.getUserName());
                    UserRoleRef ur = new UserRoleRef();
                    ur.setUserId(user.getId());
                    ur.setRoleId(Enums.Role.USER.getId());
                    userRoleService.addUserRole(ur);
                    
                    loginUserName = nickName;
                    loginUserPwd = CryptoUtils.encodeMD5("123456");//默认登陆密码123456
                }else{//已经注册登陆过
                    loginUserName = userObj.getUserName();
                    loginUserPwd = userObj.getPassword();
                }
                
                UsernamePasswordToken token = new UsernamePasswordToken();  
                token.setUsername(loginUserName);  
                token.setPassword(loginUserPwd.toCharArray());  
                SecurityUtils.getSubject().login(token);
                
                LoggerUtil.LoggerFormatPattern("用户：{0} 登录成功", loginUserName);
                SecurityUtils.getSubject().getSession().setTimeout(1000 * 60 * 60);
                
                mav = new ModelAndView("index");
                request.getSession().setAttribute("nickName", loginUserName);
                request.getSession().setAttribute("logoImg", userInfoBean.getAvatar().getAvatarURL30());
                //mav.addObject("nickName", loginUserName);
                //mav.addObject("logoImg", userInfoBean.getAvatar().getAvatarURL30());
                
                PageVo<Article> articleList = null;
                try {
                    articleList = articleService.getArticleList(new ArticleQo());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mav.addObject(articleList);
            }
        } catch (QQConnectException e) {
            mav = new ModelAndView("login");
            mav.addObject("loginErrorMsg", "QQ快捷登陆失败");
        }
        return mav;
    }
}
